/*
*  Circle3D.cpp
*
*  Created on: Jan 14, 2012
*  
*/

#pragma region INCLUDEs
//
#include "Circle3D.h"
#include "Box3D.h"
#include "MathHelper.h"

#include <iostream>
using namespace std;
//
#pragma endregion 



namespace Physics
{
	//Re-Declare static variable for Compiler Pre-Processing
	int Circle3D::cir3D_InstanceCount = 0;

#pragma region CONSTRUCTORs
	//C001: Default Constructor
	Circle3D::Circle3D()
	{
		this->radius = 1;

		this->objID = ZERO;
		++cir3D_InstanceCount;
	}
	
	//C002: Overloaded Constructor
	Circle3D::Circle3D(const float radius, const Vector3 &pos = Vector3() )
	{
		this->radius = ( radius < 1 ) ? 1 : radius;
		this->position = pos;

		this->objID = ZERO;
		++cir3D_InstanceCount;
	}

	//C003: Overloaded Constructor
	Circle3D::Circle3D(const float radius, const Vector3 &pos = Vector3(), const Vector3 &dir = Vector3() )
	{
		this->radius = ( radius < 1 ) ? 1 : radius;
		this->position = pos;
		this->direction = dir;

		this->objID = ZERO;
		++cir3D_InstanceCount;
	}

	//C004: Overloaded Constructor
	Circle3D::Circle3D(const float radius, const Vector3 &pos = Vector3(), const Vector3 &dir = Vector3(), const float speed = 0, const float mass = 0 )
	{
		this->radius = ( radius < 1 ) ? 1 : radius;
		this->position = pos;
		this->direction = dir;

		this->speed = speed;
		this->mass = mass;

		this->objID = ZERO;
		++cir3D_InstanceCount;
	}

	//C005: COPY Constructor
	Circle3D::Circle3D( const Circle3D &circle )
	{
		this->radius = circle.getRadius();
		this->position = circle.getPosition();
		this->direction = circle.getDirection();

		this->speed = circle.getSpeed();
		this->mass = circle.getMass();

		this->objID = circle.getID();
		++cir3D_InstanceCount;
	}

	//C006: Assignment Operator
	Circle3D& Circle3D::operator=( const Circle3D &circle )
	{
		if ( this != &circle )
		{
			this->radius = circle.getRadius();
			this->position = circle.getPosition();
			this->direction = circle.getDirection();

			this->speed = circle.getSpeed();
			this->mass = circle.getMass();

			this->objID = circle.getID();
			++cir3D_InstanceCount;
		}
		return *this;
	}

	//C007: Virtual Destructor
	Circle3D::~Circle3D() 
	{ 
		//decrement global active objects' counter
		IPhysicsObject::decrement_ObjectCount(); 

		//decrement circle3D Instance Counter
		( ( cir3D_InstanceCount > 0 ) ? --cir3D_InstanceCount : cir3D_InstanceCount = 0 );
	}
#pragma endregion


	//M022: Getter Instance Count
	const int Circle3D::count()
	{
		return cir3D_InstanceCount;
	}


#pragma region RADIUS_PROPERTIES
	//M001: Setter Radius
	void Circle3D::setRadius(const float radius)
	{
		this->radius = ( ( radius < 1 ) ?  1 : radius );
	}

	//M002: Getter Radius
	const float Circle3D::getRadius() const  { return this->radius; }
	//
#pragma endregion


#pragma region IPhysicsObject_3D_METHODs
	//M023: Print Summary Info about instance object
	void Circle3D::Info()
	{
		cout << "\n======================================================\n" << endl;
		cout << "\nCircle3D Obj Info:\n" << endl;
		cout << "\n--------------------------------------------------------\n" << endl;

		cout << "Object ID: " << this->objID << endl << endl;

		cout << "Position XYZ: (" << this->position.getX() << ", " << this->position.getY() << ", " << this->position.getZ() << ")" << endl;
		cout << "Direction XYZ: (" << this->direction.getX() << ", " << this->direction.getY() << ", " << this->direction.getZ() << ")" << endl;
		cout << "Speed: " << this->speed << endl;
		cout << "Mass: " << this->mass << endl;

		cout << "Radius: " << this->radius << endl;

		cout << "\n======================================================\n" << endl << endl;
	}
#pragma endregion


#pragma region ICOLLISION_3D_METHODS
	//M003: THIS -> Box3D collision check
	bool Circle3D::collision(const Box3D &box)
	{
		Vector3 center = this->getCenter();
		
		float sqrDist = MathHelper::sqrDistancePointToCube(center, box);
		float sqrRadius = this->radius * this->radius;

		return( (sqrDist > sqrRadius) ? false : true);
	}

	//M004: THIS -> Circle3D collision check
	bool Circle3D::collision(const Circle3D &circle)
	{
		float dist = MathHelper::findDistance( this->getCenter(), circle.getCenter() );

		return ( dist <= (this->getRadius() + circle.getRadius()) ) ? true : false;
	}
#pragma endregion



#pragma region SHAPE_3D_METHODS
	//
	//M005: Getter Center
	const Vector3 Circle3D::getCenter() const
	{
		//float x = this->position.getX() + this->radius;
		//float y = this->position.getY() + this->radius;
		//float z = this->position.getZ() + this->radius;
		return this->position;
	}

	//==================== SETTER: ROTATION_3D ====================
	//Applied to XYZ Directions
	//-----------------------------
	//M006: Rotation input Vector3 in DEGREES	
	void Circle3D::rotateInDegs(const Vector3 &degrees)
	{
		//Implementation Code goes here...
	}

	//M007: Rotation input float in DEGREES
	void Circle3D::rotateInDegs(const float degrees)
	{
		//Implementation Code goes here...
	}

	//M008: Rotation input floats in DEGREES
	void Circle3D::rotateInDegs(const float X, const float Y, const float Z)
	{
		//Implementation Code goes here...
	}		


	//Applied to XYZ Directions
	//-----------------------------
	//M009: Rotation input Vector3 in RADIANS
	void Circle3D::rotateInRads(const Vector3 &radians)
	{
		//Implementation Code goes here...
	}

	//M010: Rotation input float in RADIANS
	void Circle3D::rotateInRads(const float radians)
	{
		//Implementation Code goes here...
	}

	//M011: Rotation input floats in RADIANS
	void Circle3D::rotateInRads(const float X, const float Y, const float Z)
	{
		//Implementation Code goes here...
	}


	//Applied to X-Direction
	//-----------------------------
	//M012: Rotation input float in DEGREES
	void Circle3D::rotateX_InDegs(const float degrees)
	{
		//Implementation Code goes here...
	}

	//M013: Rotation input float in RADIANS
	void Circle3D::rotateX_InRads(const float radians)
	{
		//Implementation Code goes here...
	}


	//Applied to Y-Direction
	//-----------------------------
	//M014: Rotation input float in DEGREES
	void Circle3D::rotateY_InDegs(const float degrees)
	{
		//Implementation Code goes here...
	}

	//M015: Rotation input float in RADIANS
	void Circle3D::rotateY_InRads(const float radians)
	{
		//Implementation Code goes here...
	}


	//Applied to Z-Direction
	//-----------------------------
	//M016: Rotation input float in DEGREES
	void Circle3D::rotateZ_InDegs(const float degrees)
	{
		//Implementation Code goes here...
	}

	//M017: Rotation input float in RADIANS
	void Circle3D::rotateZ_InRads(const float radians)
	{
		//Implementation Code goes here...
	}
	//==================== SETTER: ROTATION_3D ====================



	//==================== SETTER: TRANSLATION_3D ====================
	//TRANSLATION_POSITION
	//
	//M018: Translate Position using float
	void Circle3D::translatePosition(const float X, const float Y, const float Z)
	{
		this->position.setXYZ( this->position.getX() + X, this->position.getY() + Y, this->position.getZ() + Z );
	}

	//M019: Translate Position using Vector3
	void Circle3D::translatePosition(const Vector3 &value)
	{
		this->position.setXYZ( this->position + value );
	}

	//TRANSLATION_DIRECTION
	//
	//M020: Translate Direction using floats
	void Circle3D::translateDirection(const float X, const float Y, const float Z)
	{
		//Implementation Code goes here...
	}

	//M021: Translate Direction using Vector3
	void Circle3D::translateDirection(const Vector3 &value)							
	{
		//Implementation Code goes here...
	}

	//==================== SETTER: TRANSLATION_3D ====================

#pragma endregion

} /* NAMESPACE */
